package com.hejia.alauda.service;

import java.io.StringWriter;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONObject;
import com.hejia.alauda.entity.Agreement;
import com.hejia.alauda.entity.Financing;
import com.hejia.alauda.entity.Interest;
import com.hejia.alauda.entity.Product;
import com.hejia.alauda.entity.ProductTypeValue;
import com.hejia.alauda.entity.Protocol;
import com.hejia.alauda.entity.User;
import com.hejia.alauda.entity.example.AgreementExample;
import com.hejia.alauda.entity.example.FinancingExample;
import com.hejia.alauda.entity.example.InterestExample;
import com.hejia.alauda.entity.example.RepaymentOrderExample;
import com.hejia.alauda.persistence.mybatis.AgreementMapper;
import com.hejia.alauda.persistence.mybatis.BonusRecordMapper;
import com.hejia.alauda.persistence.mybatis.FinancingMapper;
import com.hejia.alauda.persistence.mybatis.InterestMapper;
import com.hejia.alauda.persistence.mybatis.RepaymentOrderMapper;
import com.hejia.alauda.utils.CnUpperCaser;
import com.hejia.alauda.utils.Pager;
import com.hejia.alauda.utils.Utils;

import freemarker.template.Template;

@Service
public class FinancingServiceImpl implements FinancingService{

	@Value("#{settings['agreement.url.prefix']}")
	protected String agreementUrlPrefix;
	
	Log logger = LogFactory.getLog(FinancingServiceImpl.class);
	
	//Mappers
	@Resource
	private FinancingMapper financingMapper;
	
	@Resource
	private AgreementMapper agreementMapper;
	
	@Resource
	private InterestMapper interestMapper;
	
	//Services
	@Resource
	private ProductService productService;
	
	@Resource
	private CommonService commonService;
	
	@Resource
	private BonusRecordMapper bonusRecordMapper;
	
	@Resource
	private RepaymentOrderMapper repaymentOrderMapper;
	
	
	

	@Override
	public Pager<Financing> findInterestFinancingByProduct(Product product, Pager<Financing> pager) {
		
		FinancingExample example = new FinancingExample();
		example.appendCriterion("product_id=", product.getId());
		example.appendCriterion("status=", "STATUS_INTEREST");
		example.setOrderByClause(pager.getOrderBy());
		List<Financing> list = financingMapper.selectByExample(example, pager);
		pager.setList(list);
		
		return pager;
	}
	
	@Override
	public Pager<Financing> findFinancingByProduct(Product product, Pager<Financing> pager) {
		
		FinancingExample example = new FinancingExample();
		example.appendCriterion("product_id=", product.getId());
		example.setOrderByClause(pager.getOrderBy());
		List<Financing> list = financingMapper.selectByExample(example, pager);
		int totalCount = financingMapper.countByExample(example);
		pager.setList(list);
		pager.setTotalCount(totalCount);
		
		return pager;
	}

	@Override
	public Pager<Financing> findFinancingByUser(User user, String type, Pager<Financing> pager) {
		if(type == null)
			type = "";
		FinancingExample example = new FinancingExample();
		example.appendCriterion("user_id=", user.getId());
		switch(type.toLowerCase()){
			case "prepare":
				example.appendCriterion("status=", "STATUS_DEFAULT");
				break;
				
			case "interest":
				example.appendCriterion("status=", "STATUS_INTEREST");
				break;
				
			case "apply":
				example.appendCriterion("status=", "STATUS_PAYAPPLY");
				break;
				
			case "repaid":
				example.appendCriterion("status=", "STATUS_REPAID");
				break;				
		}
				
		example.setOrderByClause(" field(status,'STATUS_DEFAULT','STATUS_INTEREST','STATUS_PAYAPPLY','STATUS_REPAID'), repaymentTime desc,createDate desc ");
		List<Financing> list = financingMapper.selectByExample(example, pager);
		int totalCount = financingMapper.countByExample(example);
		
		pager.setTotalCount(totalCount);
		pager.setList(list);
		
		return pager;
	}

	@Override
	public Financing getFinancingById(Long id) {

		return financingMapper.selectByPrimaryKey(id);
	}
	
	@Override
	public String renderingProtocolContent(String tid, String templateContent,
			User user, Financing financing, Long productId){
		return renderingProtocolContent(tid, templateContent, user ,financing, productId, null);
	}
	/**
	 * 渲染协议内容
	 * 
	 * @param tid
	 *            模版id
	 * @param templateContent
	 *            模版内容
	 * @param user
	 *            用户信息
	 * @param financing
	 *            金融包信息
	 * @param productId
	 *            产品id(从产品分类中渲染时使用，否则为空)
	 * @return
	 */
	@Override
	public String renderingProtocolContent(String tid, String templateContent,
			User user, Financing financing, Long productId, String serial) {
		try {
			Template tmplt = new Template(tid, templateContent, null);
			StringWriter rest = new StringWriter();
			Map<String, Object> params = new HashMap<String, Object>();

			if(Strings.isNotBlank(serial))
				params.put("serialNo", serial);
			/*
			 * 设置协议自定义变量
			 */
			if (productId != null) {
				Product product = productService.getProductById(productId);
				ProductTypeValue ptv = productService
						.findProductTypeValueByProductId(product.getId());

				if (ptv != null) {
					JSONObject json = JSONObject.parseObject(ptv.getValue());
					Iterator<String> iterator = json.keySet().iterator();
					while (iterator.hasNext()) {
						String key = iterator.next();
						params.put(key, json.get(key));
					}
				}
				params.put("product", product);
			}

			/*
			 * 设置用户信息及金融包信息
			 */
			params.put("user", user);
			params.put("financing", financing);
			BigDecimal interest = null;// 总收益
			if (financing.getAmount() != null) {
				params.put("bigAmount", Utils.digitUppercase(financing.getAmount()
						.doubleValue()));
				params.put("amount", financing.getAmount().toString());
				interest = new BigDecimal(financing.getAmount().doubleValue()
						* (financing.getInterestRate().doubleValue()) / 360
						* financing.getTerm()).setScale(2, RoundingMode.UP);
			}
			if (interest != null) {
				params.put("bigIncome",
						new CnUpperCaser(interest.toString()).getCnString());
				params.put("income", interest.doubleValue());
			}
			SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
			String date = formatter.format(financing.getCreateDate());
			params.put("createDate", date);
			tmplt.process(params, rest);
			return rest.toString();
		} catch (Exception e) {
			logger.error(Utils.getExceptionLog(e));
			return null;
		}
	}
	
	@Override
	public Boolean generateAgreement(Financing financing){
		 SimpleDateFormat formatter = new SimpleDateFormat("yyMMdd");
		Product product = financing.getProduct();
		User user = financing.getUser();
		String content = null;
		String serial = commonService.getAgreementSerial(formatter.format(financing.getCreateDate()));
		
		
		
		String protocols =  product.getType().getProtocols();
		String[] protocolsIds   = protocols.split(",");
		
		for(String protocolsId:protocolsIds){
			
			Agreement agreement = new Agreement();
			agreement.setSerial(serial);
			agreement.setFinancing(financing);
			agreement.setUser(user);
			
			if (product.getType() != null) {
				/*
				 * 使用产品分类中的协议
				 */	
				Long protocolId = Long.valueOf(protocolsId);
				com.hejia.alauda.entity.Template tpl = productService.getTemplateById(protocolId);
				agreement.setTitle(tpl.getName());
				content = renderingProtocolContent(
						protocolId.toString(), tpl.getContent(), user, financing, product.getId(), serial);
				
			} else {
				/*
				 * 使用产品本身的协议
				 */
				Protocol protocol = productService.findProtocolById(product.getId());
				agreement.setTitle(protocol.getTitle());
				content = renderingProtocolContent(product.getId().toString(),
						protocol.getContent(), user, financing, null, serial);
				
			}
			agreement.setContent(content);
			agreementMapper.insert(agreement);
		}
		
		
		financing.setAgreementNumber(serial);
		financingMapper.updateByPrimaryKey(financing);
		
		
		return true;
	}

	@Override
	public List<Map<String, String>> findAgreementsByFinancing(Financing financing) {
		AgreementExample example = new AgreementExample();
		example.appendCriterion("financing_id=", financing.getId());
		List<Agreement> list = agreementMapper.selectByExample(example, new Pager<Agreement>());
		List<Map<String, String>> agreementList = new ArrayList<Map<String, String>>();
		for(Agreement a:list){
			Map<String, String> map = new HashMap<String, String>();
			map.put("url",agreementUrlPrefix + a.getSerial());
			map.put("title", a.getTitle());
			agreementList.add(map);
		}
		return agreementList;
	}
	
	@Override
	public Agreement getAgreementBySerial(String serial){
		AgreementExample example = new AgreementExample();
		example.appendCriterion("serial=", serial);
		return agreementMapper.selectOneByExample(example);
	}

	@Override
	public List<Interest> findInterestByUser(User user, String date) {
		InterestExample example = new InterestExample();
		example.appendCriterion("user_id=", user.getId());
		example.appendCriterion("valueDate=", date);
		
		Pager<Interest> pager = new Pager<Interest>();
		pager.setPageSize(Integer.MAX_VALUE);
		return interestMapper.selectByExample(example, pager);
	}

	@Override
	public BigDecimal sumFinancingByTime(User user, String begin, String end) {
		FinancingExample example = new FinancingExample();
		example.appendCriterion("user_id=", user.getId());
		example.appendCriterion("createDate>", begin);
		example.appendCriterion("createDate<", end);
		Double total = financingMapper.sumByExample("amount", example);
		return new BigDecimal(total);
	}

	@Override
	public Map<String, Object> findTotalIncomeByUser(User user) {
		Map<String, Object> totalIncome = new HashMap<String, Object>();
		
		//总红包
		BigDecimal redEnvelope= this.bonusRecordMapper.findSumAmountByUser(user);
		
		//VIP 加息
		RepaymentOrderExample repaymentOrderExample = new RepaymentOrderExample();
		repaymentOrderExample.appendCriterion("userId = ", user.getId());
		repaymentOrderExample.appendCriterion("description like ", "%VIP%");
		repaymentOrderExample.appendCriterion("status = ", "STATUS_SUCCESS");
		BigDecimal VIPAmount = BigDecimal.valueOf(this.repaymentOrderMapper.sumByExample("amount", repaymentOrderExample));
		
		//总收益
		FinancingExample financingExample = new FinancingExample();
		financingExample.appendCriterion("user_id=", user.getId());
		BigDecimal income = BigDecimal.valueOf(this.financingMapper.sumByExample("income", financingExample));
		
		totalIncome.put("redEnvelope", redEnvelope); 
		totalIncome.put("VIPAmount", VIPAmount);
		//总收益 = 红包  + VIP加息 + 收益
		totalIncome.put("income", income.add(redEnvelope).add(VIPAmount));
		
		return totalIncome;
	}
	/**
	 * 查询历史最高资产及收益
	 * 
	 * @param user
	 * @return
	 */
	public Map<String, Object> findPastMaxAssetByUser(User user){
		Map<String, Object> maxAsset = this.financingMapper.selectPastMaxAssetByUser(user.getId());
		
		BigDecimal amount = BigDecimal.valueOf(Double.parseDouble(maxAsset.get("amount").toString()));
		BigDecimal income = BigDecimal.valueOf(Double.parseDouble(maxAsset.get("income").toString()));

		maxAsset.put("amount", amount.add(income));
		return maxAsset;
	}
	
}
